#pragma once

#include <functional>
#include <memory>

#include "netlib/base/noncopyable.h"
#include "netlib/base/time_stamp.h"
#include "netlib/net/socket/buffer.h"

namespace netlib::net {
class TcpConnection;
using TcpConnectionPtr = std::shared_ptr<TcpConnection>;
} // namespace netlib::net

namespace google::protobuf {
class Message;
} // namespace google::protobuf

namespace netlib::rpc {

using ProtobufMessage = ::google::protobuf::Message;

template <typename MSG> class ProtobufCodec : public NonCopyable {
public:
	using ProtobufMessageCallback = std::function<void(
	    const net::TcpConnectionPtr&, std::unique_ptr<ProtobufMessage>&&, Timestamp)>;

	explicit ProtobufCodec(ProtobufMessageCallback&& cb);

	void Send(const net::TcpConnectionPtr& conn, const ProtobufMessage& msg) const;
	void OnMessage(const net::TcpConnectionPtr& conn, net::Buffer* buf, Timestamp time) const;

private:
	const ProtobufMessage* pb_type_;
	ProtobufMessageCallback msg_callback_;

	constexpr static uint32_t kHeaderSizeSize = net::Buffer::kHeaderSizeSize;
	constexpr static uint32_t kCheckSumSize = net::Buffer::kCheckSumSize;
	constexpr static uint32_t kMinMessageSize = net::Buffer::kCheckSumSize;
	constexpr static uint32_t kMaxMessageSize = 1024 * 1024 * 64;
};

} // namespace netlib::rpc